home *** CD-ROM | disk | FTP | other *** search
- ; example of writing assembler for use in APCS environment
-
- ; in STM/LDM instructions rx..ry indicates any combinations
- ; (0 or more) of x..y may be present
-
- ; x$stack_overflow and x$stack_overflow_1 are provided by
- ; the run time kernel
-
- ;------------------------------------------------------------------------------------------------------
-
- ; this next block identifies this routine
- ; should a backtrace be required
-
- = "procedure name",0
- ALIGN
- & &FF0000xx ; xx is positive offset from this word back to start of string
- ; eg "abcde",0 needs a value of &FF000008 (remember to include padding from ALIGN)
-
- procedure
- MOV ip,sp
- ; optional instruction to save arguments on entry
- ; STMDB sp!,{r0..r3}
- STMDB sp!,{r4..r9,fp,ip,lr,pc}
- SUB fp,ip,#4
-
- ; only one of the following 3 peices of code should be used next
- ; depending on amount of stack used etc
-
- ; (1) procedure will use no more than 512 bytes of stack and
- ; will not call an external procedure
- ; (internal routines can be considered as part of this one
- ; provided they use a fixed amount of stack)
-
- ; no code required
- ; guaranteed 512 bytes of space left on stack
-
-
- ; (2) procedure will use no more than 256 bytes of stack and
- ; may call an external procedure
-
- CMP sp,sl
- BLLO |x$stack_overflow|
-
-
- ; (3) (a) procedure may use more than 512 bytes of stack
- ; (and may or may not call external procedure)
- ; OR
- ; (b) procedure may use more than 256 bytes of stack and
- ; may call external procedure
-
- SUB ip,sp,#amount_of_stack_space_needed_in_bytes
- CMP ip,sl
- BLLO |x$_stack_overflow_1|
- ; typical instruction to drop sp for local space
- SUB sp,sp,#amount_of_stack_space_needed_in_bytes
- ; more code which uses local space,
- ; always accessed using postive offsets from sp
- ; eg STR r0,[sp,#positive_offset]
-
-
- ; main procedure body
- ; to access arguments which may have been pushed on stack
- ; also access with -ve offsets from fp
- ; eg LDR r0,[fp,#negative_offset]
-
- ; remember to count stack use of internal subroutines
- ; as part of this procedure
- BL internal_subroutine
-
- ; when calling an external procedure,
- ; sl,sp must be valid
- BL external_procedure
- ; on return: r0-r3,ip,lr may be corrupted; r4-r9,sl,fp are preserved
- ; PSR flags are preserved
- ; (lr corrupted implies it may contain anything, not just the return
- ; address setup by the BL)
-
- ; more code
- ; must preserve sl,fp
- ; may corrupt r0-r3,ip,lr
- ; may corrupt r4..r9 but only if they are stacked at entry/exit
-
-
- ; when returning sl,fp must be valid
-
- MOV r0,#return_value
- ; return with value in r0
- LDMDB fp,{r4..r9,fp,sp,pc}^
-
-
- ;------------------------------------------------------------------------------------------------------
-
- EXTRA NOTES:
-
- In leaf procedures (ones that call no other external procedures)
- various optimisations can be made to the entry/exit sequence.
-
- eg
- procedure
- LDR r0,[r0,#Offset]
- MOVS pc,lr
-
- It is important that a procedure always returns the flags using lr
- (usually stacked) and not the flags on entry. Consider the following
- example of a tail-optimised procedure calling an external procedure:
-
- procedureA
- CMP r0,#value
- MOVLO r1,#constX
- MOVHS r1,#constY
- B procedureB
-
- If procedureB was to restore the flags it saw on entry
- (not those in lr) then it will return to A's caller with the
- wrong flags.
-